/* Copyright (c) 2021 OceanBase and/or its affiliates. All rights reserved.
miniob is licensed under Mulan PSL v2.
You can use this software according to the terms and conditions of the Mulan PSL v2.
You may obtain a copy of Mulan PSL v2 at:
         http://license.coscl.org.cn/MulanPSL2
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details. */

//
// Created by Longda on 2021/4/13.
//

#include <string.h>

#include "parse_stage.h"

#include "common/conf/ini.h"
#include "common/io/io.h"
#include "common/lang/string.h"
#include "common/log/log.h"
#include "event/session_event.h"
#include "event/sql_event.h"
#include "sql/parser/parse.h"

using namespace common;

//调用ParaseStage::handle_request()函数，这是处理SQL请求的入口方法
RC ParseStage::handle_request(SQLStageEvent *sql_event)
{
  RC rc = RC::SUCCESS;

  SqlResult         *sql_result = sql_event->session_event()->sql_result();
  const string &sql        = sql_event->sql();

  //存储SQL解析结果
  ParsedSqlResult parsed_sql_result;
  //调用parse函数进行SQL解析 SQL 字符串（sql.c_str() 转为 C 风格字符串）和结果存储对象 parsed_sql_result
  parse(sql.c_str(), &parsed_sql_result);
  //如果解析后没有生成任何 SQL 节点 返回 RC::INTERNAL（内部错误），表示解析阶段出现异常
  if (parsed_sql_result.sql_nodes().empty()) {
    sql_result->set_return_code(RC::SUCCESS);
    sql_result->set_state_string("");
    return RC::INTERNAL;
  }
  //如果解析后生成了多个 SQL 节点，打印警告日志，表示miniob只会处理第一个 SQL 节点
  if (parsed_sql_result.sql_nodes().size() > 1) {
    LOG_WARN("got multi sql commands but only 1 will be handled");
  }
  //取出第一个 SQL 节点，使用 unique_ptr 管理其生命周期，转移节点所有权到 sql_node
  unique_ptr<ParsedSqlNode> sql_node = std::move(parsed_sql_result.sql_nodes().front());
  //如果解析出的节点标记为 SCF_ERROR，说明 SQL 存在语法错误（比如 CALC 1+ 这类不完整的表达式）
  if (sql_node->flag == SCF_ERROR) {
    // set error information to event
    rc = RC::SQL_SYNTAX;
    sql_result->set_return_code(rc);
    sql_result->set_state_string("Failed to parse sql");
    return rc;
  }
  //如果SQL合法，将解析出的 SQL 节点设置到 SQL 事件中，转移所有权到 sql_event
  sql_event->set_sql_node(std::move(sql_node));

  return RC::SUCCESS;
}
